#include <stdio.h>  
#include <unistd.h>  
#include <sys/mman.h>  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <fcntl.h>  
#include <string.h>

//GPIO控制器地址&大小
#define GPIO_Base_addr 0xFED0E000    //BS:0xFED0E000  WC:0xFED0C000  LT:0xFED0C000
#define GPIO_Page_size 4096
//GPIO配置寄存器偏移量
#define GPIO1_CFG_ADDR 0x340  //BS:0x200  WC:0x2E0   //INPUT0  -> 1L
#define GPIO2_CFG_ADDR 0x350  //BS:0x220  WC:0x290   //INPUT1  -> 2L
#define GPIO3_CFG_ADDR 0x310  //BS:0x240  WC:0x2D0   //INPUT2  -> 4L
#define GPIO4_CFG_ADDR 0x370  //BS:0x260  WC:0x2A0   //INPUT3  -> 8L
#define GPIO5_CFG_ADDR 0x300  //BS:0x170  WC:0x2B0   //OUTPUT0 -> 1H
#define GPIO6_CFG_ADDR 0x390  //BS:0x270  WC:0x2C0   //OUTPUT1 -> 2H
#define GPIO7_CFG_ADDR 0x320  //BS:0x1C0  WC:0x650   //OUTPUT2 -> 4H
#define GPIO8_CFG_ADDR 0x3A0  //BS:0x1B0  WC:0x3A0   //OUTPUT3 -> 8H
#define GPIO9_CFG_ADDR 0x330  
//GPIO端口值寄存器偏移量
#define GPIO1_PORT_ADDR (GPIO1_CFG_ADDR+8)
#define GPIO2_PORT_ADDR (GPIO2_CFG_ADDR+8)
#define GPIO3_PORT_ADDR (GPIO3_CFG_ADDR+8)
#define GPIO4_PORT_ADDR (GPIO4_CFG_ADDR+8)
#define GPIO5_PORT_ADDR (GPIO5_CFG_ADDR+8)
#define GPIO6_PORT_ADDR (GPIO6_CFG_ADDR+8)
#define GPIO7_PORT_ADDR (GPIO7_CFG_ADDR+8)
#define GPIO8_PORT_ADDR (GPIO8_CFG_ADDR+8)
#define GPIO9_PORT_ADDR (GPIO9_CFG_ADDR+8)
//GPIO默认配置值
#define GPIO_CFG_Value  0x2003CD00
#define GPIO_PORT_CFG_Value  0x00000003
//打印调试信息
#define DEBUG 1
int main (int args, char* arg[])  
{  
    int fd;  
    char* mem;  
    int TMP=0;
    int Value=0;

    //open /dev/mem with read and write mode  
    if((fd = open ("/dev/mem", O_RDWR|O_SYNC)) < 0)  
    {  
        perror ("open error");  
        return -1;  
    }  

    //map physical memory 0-10 bytes  
    mem = mmap (0, GPIO_Page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO_Base_addr);  
    if (mem == MAP_FAILED)  
    {  
        perror ("mmap error:");  
        return 1;  
    }  

#if DEBUG==0||DEBUG==1
    //读写方式1
    //printf("Code1\n");
    //写入GPIO基础配置 
    TMP=GPIO_CFG_Value;
    memcpy((mem+GPIO1_CFG_ADDR),&TMP, 4);
    memcpy((mem+GPIO2_CFG_ADDR),&TMP, 4);
    memcpy((mem+GPIO3_CFG_ADDR),&TMP, 4);
    memcpy((mem+GPIO4_CFG_ADDR),&TMP, 4);
    memcpy((mem+GPIO5_CFG_ADDR),&TMP, 4);
    memcpy((mem+GPIO6_CFG_ADDR),&TMP, 4);
    memcpy((mem+GPIO7_CFG_ADDR),&TMP, 4);
    memcpy((mem+GPIO8_CFG_ADDR),&TMP, 4);
	memcpy((mem+GPIO9_CFG_ADDR),&TMP, 4);
    TMP=0;
    //写入GPIO输入输出配置 
    TMP=GPIO_PORT_CFG_Value;
    memcpy((mem+GPIO1_PORT_ADDR),&TMP, 4);
    memcpy((mem+GPIO2_PORT_ADDR),&TMP, 4);
    memcpy((mem+GPIO3_PORT_ADDR),&TMP, 4);
    memcpy((mem+GPIO4_PORT_ADDR),&TMP, 4);
    memcpy((mem+GPIO5_PORT_ADDR),&TMP, 4);
    memcpy((mem+GPIO6_PORT_ADDR),&TMP, 4);
    memcpy((mem+GPIO7_PORT_ADDR),&TMP, 4);
    memcpy((mem+GPIO8_PORT_ADDR),&TMP, 4);
	memcpy((mem+GPIO9_PORT_ADDR),&TMP, 4);
    TMP=0;

    sleep(1);
    //计算编码器值
    Value=( 
            ((*((int *)(mem+GPIO1_PORT_ADDR))&0x01)) |
            ((*((int *)(mem+GPIO2_PORT_ADDR))&0x01)<<1) |
            ((*((int *)(mem+GPIO3_PORT_ADDR))&0x01)<<2) |
            ((*((int *)(mem+GPIO4_PORT_ADDR))&0x01)<<3) |
            ((*((int *)(mem+GPIO5_PORT_ADDR))&0x01)<<4) |
            ((*((int *)(mem+GPIO6_PORT_ADDR))&0x01)<<5) | 
            ((*((int *)(mem+GPIO7_PORT_ADDR))&0x01)<<6) | 
            ((*((int *)(mem+GPIO8_PORT_ADDR))&0x01)<<7) );
    printf("%02X\n",(unsigned char)(~Value));
#endif

#if DEBUG==1
    //输出GPIO寄存器信息
    sleep(1);
    printf("GPIO1 1L The address: 0x%lX CFG:value 0x%08X PORT:value 0x%08X\n",  (unsigned long)(mem+GPIO1_CFG_ADDR),*((int *)(mem+GPIO1_CFG_ADDR)),*((int *)(mem+GPIO1_PORT_ADDR)));  
    printf("GPIO2 2L The address: 0x%lX CFG:value 0x%08X PORT:value 0x%08X\n",  (unsigned long)(mem+GPIO2_CFG_ADDR),*((int *)(mem+GPIO2_CFG_ADDR)),*((int *)(mem+GPIO2_PORT_ADDR))); 
    printf("GPIO3 4L The address: 0x%lX CFG:value 0x%08X PORT:value 0x%08X\n",  (unsigned long)(mem+GPIO3_CFG_ADDR),*((int *)(mem+GPIO3_CFG_ADDR)),*((int *)(mem+GPIO3_PORT_ADDR))); 
    printf("GPIO4 8L The address: 0x%lX CFG:value 0x%08X PORT:value 0x%08X\n",  (unsigned long)(mem+GPIO4_CFG_ADDR),*((int *)(mem+GPIO4_CFG_ADDR)),*((int *)(mem+GPIO4_PORT_ADDR))); 
    printf("GPIO5 1H The address: 0x%lX CFG:value 0x%08X PORT:value 0x%08X\n",  (unsigned long)(mem+GPIO5_CFG_ADDR),*((int *)(mem+GPIO5_CFG_ADDR)),*((int *)(mem+GPIO5_PORT_ADDR))); 
    printf("GPIO6 2H The address: 0x%lX CFG:value 0x%08X PORT:value 0x%08X\n",  (unsigned long)(mem+GPIO6_CFG_ADDR),*((int *)(mem+GPIO6_CFG_ADDR)),*((int *)(mem+GPIO6_PORT_ADDR))); 
    printf("GPIO7 4H The address: 0x%lX CFG:value 0x%08X PORT:value 0x%08X\n",  (unsigned long)(mem+GPIO7_CFG_ADDR),*((int *)(mem+GPIO7_CFG_ADDR)),*((int *)(mem+GPIO7_PORT_ADDR))); 
    printf("GPIO8 8H The address: 0x%lX CFG:value 0x%08X PORT:value 0x%08X\n",  (unsigned long)(mem+GPIO8_CFG_ADDR),*((int *)(mem+GPIO8_CFG_ADDR)),*((int *)(mem+GPIO8_PORT_ADDR))); 
	printf("GPIO9    The address: 0x%lX CFG:value 0x%08X PORT:value 0x%08X\n",  (unsigned long)(mem+GPIO9_CFG_ADDR),*((int *)(mem+GPIO9_CFG_ADDR)),*((int *)(mem+GPIO9_PORT_ADDR))); 

    //输出整个映射空间数据
    unsigned i=0,a=0;
    unsigned long addr;
    unsigned long content;
    addr = (unsigned long)(mem + i);
    printf("address: 0x%lx ", addr);
    for (;i < GPIO_Page_size; )
    {

        if(a==4)
        {
            addr = (unsigned long)(mem + i);
            printf("\naddress: 0x%lx ", addr);
                addr = (unsigned long)(mem + i);
            a=0;
        }

        content =*((int *)(mem+i));

        printf("0x%08X ",content);

	    a++;
	    i=i+4;
    }
    printf("\n");

#endif

    munmap (mem, GPIO_Page_size); //destroy map memory  
    close (fd);   //close file  

    return 0;  
} 
